/*
 * tcplistenor.cpp
 *
 *  Created on: 2017年6月15日
 *      Author: work
 */

#include <dm/os/log/logger.hpp>

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <dm/os/io/tcplistener.hpp>

namespace dm{
namespace os{
namespace io{

static const char* logModule = "CTcpListener.io.os.dm";

CTcpListener::type_t CTcpListener::type()const{
	return com::CAddress::TcpServer;
}

bool CTcpListener::accept( CTcpConnect& connect ){
	if( m_fd<=0 ){
		log().warnning(THISMODULE "设备未监听");
		return false;
	}

	struct sockaddr_in client;
	socklen_t addlen = sizeof(client);
	int ac = ::accept( m_fd,(struct sockaddr*)&client,&addlen);
	if( ac<= 0 )
		return false;

	com::CTcpConnectAddr addr;
	addr.setPeerHost( inet_ntoa(client.sin_addr) );
	addr.setPeerPort( ntohs(client.sin_port) );

	connect.m_txBySend = true;
	connect.m_fd = ac;
	connect.m_address = addr;

	return true;
}

bool CTcpListener::open_in( const com::CAddress& addr ){
	const com::CTcpServerAddr* address = addr.asTcpServer();
	if( address ){
		m_fd = socket(AF_INET,SOCK_STREAM,0);
		if( m_fd<=0 ){
			log().error(THISMODULE "不能创建socket");
			return false;
		}

		int sock_reuse = 1;
		if( -1==setsockopt(m_fd,SOL_SOCKET,SO_REUSEADDR,(char*)&sock_reuse,sizeof(sock_reuse)) ){
			perror(__FUNCTION__);
		}

		struct sockaddr_in serveraddr;
		memset(&serveraddr,0,sizeof(serveraddr));
		serveraddr.sin_family = AF_INET;
		serveraddr.sin_addr.s_addr = inet_addr(address->getLocalHost());
		serveraddr.sin_port = htons(address->getLocalPort());

		if( bind(m_fd,(struct sockaddr*)&serveraddr,sizeof(serveraddr))==-1 ){
			close();
			log().warnning(THISMODULE "绑定地址失败:%s:%d",address->getLocalHost(),address->getLocalPort());
			return false;
		}

		if( listen(m_fd,1)==-1 ){
			close();
			log().error(THISMODULE "开启监听失败:%s:%d",address->getLocalHost(),address->getLocalPort());
			return false;
		}

		log().info(THISMODULE "监听TCP%s:%d开启",address->getLocalHost(),address->getLocalPort());

		return true;
	}

	return false;
}

}
}
}
